Add documentation for loading QCOW2 snapshots#98
Open
andreia-oca wants to merge 1 commit intofox-it:mainfrom
Open
Add documentation for loading QCOW2 snapshots#98andreia-oca wants to merge 1 commit intofox-it:mainfrom
andreia-oca wants to merge 1 commit intofox-it:mainfrom
Conversation
Add a section on how to use QCOW2 module to load images that are based on backing files. This is related to changes on: fox-it/dissect.hypervisor#64 Signed-off-by: Andreia Ocanoaia <andreia.ocanoaia@gmail.com>
Horofic
approved these changes
Oct 3, 2025
Comment on lines
+60
to
+101
| Open QCOW2 snapshots | ||
| ~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| For `qcow2` images there is support for backing-files and it can either be automatically loaded when opening a target. | ||
| The backing-file will automatically be read from the `qcow2` headers and dissect will attempt to load it. | ||
|
|
||
| .. code-block:: python | ||
| target = Target.open(target_path) | ||
| print(target.users()) | ||
|
|
||
| Or, for more control, the path to the backing file can be passed when initializing a `qcow2` disk: | ||
|
|
||
| .. code-block:: python | ||
| def open_qcow2_with_backing_file(snapshot_path: Path, backing_path: Path): | ||
| # Open base QCOW2 image | ||
| backing_fh = backing_path.open("rb") | ||
| base_qcow2 = qcow2.QCow2(backing_fh) | ||
| base_stream = base_qcow2.open() | ||
|
|
||
| # Open snapshot QCOW2 image with base as backing file | ||
| snapshot_fh = snapshot_path.open("rb") | ||
| snapshot_qcow2 = qcow2.QCow2( | ||
| snapshot_fh, | ||
| backing_file=base_stream | ||
| ) | ||
| snapshot_stream = snapshot_qcow2.open() | ||
|
|
||
| return snapshot_stream, snapshot_fh, backing_fh, base_stream | ||
|
|
||
| def analyze_image(snapshot_path: Path, backing_path: Path): | ||
| # Open the QCOW2 snapshot along with its backing file and get file/stream handles | ||
| snapshot_stream, snapshot_fh, backing_fh, base_stream = open_qcow2_with_backing_file(snapshot_path, backing_path) | ||
|
|
||
| # Create a new Dissect target to analyze the disk image | ||
| target = Target() | ||
| # Add the snapshot stream to the target’s disks | ||
| target.disks.add(snapshot_stream) | ||
| # Resolve all disks, volumes and filesystems and load an operating system on the current | ||
| target.apply() | ||
|
|
||
| # Collect data from the snapshot | ||
| print(target.users()) |
Member
There was a problem hiding this comment.
Hey @andreia-oca thank you for writing some documentation! I suggested some changes. Let me know what you think.
Suggested change
| Open QCOW2 snapshots | |
| ~~~~~~~~~~~~~~~~~~~~ | |
| For `qcow2` images there is support for backing-files and it can either be automatically loaded when opening a target. | |
| The backing-file will automatically be read from the `qcow2` headers and dissect will attempt to load it. | |
| .. code-block:: python | |
| target = Target.open(target_path) | |
| print(target.users()) | |
| Or, for more control, the path to the backing file can be passed when initializing a `qcow2` disk: | |
| .. code-block:: python | |
| def open_qcow2_with_backing_file(snapshot_path: Path, backing_path: Path): | |
| # Open base QCOW2 image | |
| backing_fh = backing_path.open("rb") | |
| base_qcow2 = qcow2.QCow2(backing_fh) | |
| base_stream = base_qcow2.open() | |
| # Open snapshot QCOW2 image with base as backing file | |
| snapshot_fh = snapshot_path.open("rb") | |
| snapshot_qcow2 = qcow2.QCow2( | |
| snapshot_fh, | |
| backing_file=base_stream | |
| ) | |
| snapshot_stream = snapshot_qcow2.open() | |
| return snapshot_stream, snapshot_fh, backing_fh, base_stream | |
| def analyze_image(snapshot_path: Path, backing_path: Path): | |
| # Open the QCOW2 snapshot along with its backing file and get file/stream handles | |
| snapshot_stream, snapshot_fh, backing_fh, base_stream = open_qcow2_with_backing_file(snapshot_path, backing_path) | |
| # Create a new Dissect target to analyze the disk image | |
| target = Target() | |
| # Add the snapshot stream to the target’s disks | |
| target.disks.add(snapshot_stream) | |
| # Resolve all disks, volumes and filesystems and load an operating system on the current | |
| target.apply() | |
| # Collect data from the snapshot | |
| print(target.users()) | |
| Opening QCOW2 disks & backing-files | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| The QCOW2 parser provided by this library can be used to open QCOW2 disk images, including snapshots and backing-files. | |
| When opening a QCOW2 image as a target, any backing-files are automatically loaded and resolved. | |
| For example, to open a QCOW2 image along with its backing-file: | |
| .. code-block:: python | |
| from dissect.hypervisor.disk.qcow2 import QCow2 | |
| with open("/path/to/base-image.qcow2", "rb") as base_image, \ | |
| open("/path/to/backing-file.qcow2", "rb") as backing_file: | |
| qcow2 = QCow2(base_image, backing_file=backing_file) | |
| print(qcow2.open().read(512)) | |
| print(qcow2.backing_file.read(512)) | |
| When opening a QCOW2 image using the dissect.target :class:`~dissect.target.target.Target` class, any backing-files | |
| are automatically loaded and resolved. For example: | |
| .. code-block:: python | |
| from dissect.target import Target | |
| target = Target("/path/to/base-image.qcow2") # Automatically resolves backing-files | |
| print(target.hostname) |
Comment on lines
+89
to
+101
| def analyze_image(snapshot_path: Path, backing_path: Path): | ||
| # Open the QCOW2 snapshot along with its backing file and get file/stream handles | ||
| snapshot_stream, snapshot_fh, backing_fh, base_stream = open_qcow2_with_backing_file(snapshot_path, backing_path) | ||
|
|
||
| # Create a new Dissect target to analyze the disk image | ||
| target = Target() | ||
| # Add the snapshot stream to the target’s disks | ||
| target.disks.add(snapshot_stream) | ||
| # Resolve all disks, volumes and filesystems and load an operating system on the current | ||
| target.apply() | ||
|
|
||
| # Collect data from the snapshot | ||
| print(target.users()) |
Member
There was a problem hiding this comment.
With regards to the previous suggestion. I deliberately removed this from here. I think this would be nicer suited in the /usage/use-cases.rst page.
Comment on lines
+73
to
+87
| def open_qcow2_with_backing_file(snapshot_path: Path, backing_path: Path): | ||
| # Open base QCOW2 image | ||
| backing_fh = backing_path.open("rb") | ||
| base_qcow2 = qcow2.QCow2(backing_fh) | ||
| base_stream = base_qcow2.open() | ||
|
|
||
| # Open snapshot QCOW2 image with base as backing file | ||
| snapshot_fh = snapshot_path.open("rb") | ||
| snapshot_qcow2 = qcow2.QCow2( | ||
| snapshot_fh, | ||
| backing_file=base_stream | ||
| ) | ||
| snapshot_stream = snapshot_qcow2.open() | ||
|
|
||
| return snapshot_stream, snapshot_fh, backing_fh, base_stream |
Member
There was a problem hiding this comment.
I made this more concise in the suggestion comment. Would you mind checking if it still works?
Horofic
requested changes
Oct 3, 2025
Member
Horofic
left a comment
There was a problem hiding this comment.
Oops, I meant to click "Request changes"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add a section on how to use the QCOW2 module to load
images that are based on backing files.
This is related to changes on: fox-it/dissect.hypervisor#64